package com.cyou.qb.front.interceptor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.cyou.nad.utils.jmx.MyCacheUtils;
import com.cyou.qb.constants.CacheKeyConstants;
import com.cyou.qb.constants.Constants;
import com.cyou.qb.exception.HighFrequencyException;
import com.cyou.qb.front.jmx.FrontConstants;
import com.cyou.qb.front.utils.PassportUtils;
import com.sohu.fzBranch.SohuPassport;

/**
 * 高频访问拦截器  通过Constants.FREQUENCY_INTERCEPTOR   Constants.FREQUENCY_TIME_SEGMENT_SECOND  Constants.FREQUENCY_TIMES 
 * 进行控制
 * @author luzhaoman
 *
 */
public class FrequencyInterceptor extends HandlerInterceptorAdapter implements HandlerInterceptor {
	
	private Log log = LogFactory.getLog(getClass());

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if(!FrontConstants.FREQUENCY_INTERCEPTOR)
			return true;
		String ip = PassportUtils.getUserIp(request, response);
		return Access.accessIp(ip);
	}

	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		MyCacheUtils.put("", "123", "123",false,0,10,1l);
		while(true){
			try {
				Thread.currentThread().sleep(1000);
				System.out.println(MyCacheUtils.get("","123")+"\t"+DateFormatUtils.format(new Date(), "HH:m:ss"));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Access implements Serializable{

	private static final long serialVersionUID = -6117742292725915676L;
	private final List<Date> queue = new ArrayList<Date>();
	
	public void access() {
		Calendar cal = Calendar.getInstance();
		Date n = cal.getTime();
		cal.add(Calendar.SECOND, FrontConstants.FREQUENCY_TIME_SEGMENT_SECOND*-1);
		queue.add(n);
		for (Date d : queue) {
			if (d.before(cal.getTime())) {
				queue.remove(d);
			}
		}
	}
	/**
	 * 集群高并发可能存在数据不准确
	 * @param ip
	 * @return
	 */
	public static synchronized boolean accessIp(String ip) {
		Access access = getAccess(ip);
		access.access();
		if(access.accessable()){
			return true;
		}
		throw new HighFrequencyException("访问过于频繁");
	}

	public boolean accessable() {
		return queue.size() <= FrontConstants.FREQUENCY_TIMES;
	}
	private static Access getAccess(String ip) {
		Access access  = (Access) MyCacheUtils.get("",CacheKeyConstants.ACCESS__LOG+"_"+ip);
		if(access==null){
			access= new Access();
		}
		access.access();
		MyCacheUtils.put("", CacheKeyConstants.ACCESS__LOG+"_"+ip,access,false,20*60,20*60,1l);
		return access;
	}
}


